/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "arkts_dynamic_component_renderer_impl.h"

#include <iterator>
#include <memory>

#include "accessibility_element_info.h"
#include "arkts_dynamic_renderer_loader.h"
#include "arkts_dynamic_uicontent_impl.h"

#include "interfaces/inner_api/ace/ui_content.h"
#include "native_engine/native_engine.h"

#include "adapter/ohos/entrance/ace_container.h"
#include "adapter/ohos/entrance/ui_content_impl.h"
#include "base/log/ace_trace.h"
#include "base/thread/task_executor.h"
#include "base/utils/utils.h"
#include "bridge/card_frontend/form_frontend_declarative.h"
#include "core/common/container.h"
#include "core/common/container_scope.h"
#include "core/components_ng/pattern/stage/page_pattern.h"
#include "core/components_ng/pattern/ui_extension/dynamic_component/arkts_dynamic_pattern.h"
#include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
#include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
#include "core/components_ng/pattern/window_scene/screen/screen_pattern.h"
#include "core/pipeline/pipeline_context.h"
#include "core/pipeline_ng/pipeline_context.h"
#include "render_service_client/core/ui/rs_ui_director.h"
#include "render_service_client/core/ui/rs_ui_context.h"
#include "transaction/rs_sync_transaction_controller.h"
#include "transaction/rs_transaction.h"

namespace OHOS::Ace::NG {
namespace {
constexpr int32_t INVALID_WINDOW_ID = -1;
constexpr int32_t WORKER_ERROR = 10002;
constexpr int32_t INVALID_WORKER_ID = -1;
constexpr size_t WORKER_MAX_NUM = 1;
constexpr int32_t WORKER_SIZE_ONE = 1;
constexpr int32_t DC_MAX_NUM_IN_WORKER = 4;

std::shared_ptr<AnimationOption> CopyAnimationOption(AnimationOption animationOpt)
{
    // CustomCurve and FinishCallback cannot be passed to child thread
    std::shared_ptr<AnimationOption> animationOption;
    if (animationOpt.GetCurve() && AceType::TypeId(animationOpt.GetCurve()) == Ace::CustomCurve::TypeId()) {
        animationOption = std::make_shared<AnimationOption>();
    } else {
        animationOption = std::make_shared<AnimationOption>(animationOpt);
    }
    if (animationOption) {
        animationOption->SetOnFinishEvent(nullptr);
    }

    return animationOption;
}
}

std::map<int32_t, int32_t> ArktsDynamicComponentRendererImpl::usingWorkers_;
std::mutex ArktsDynamicComponentRendererImpl::usingWorkerMutex_;

ArktsDynamicComponentRendererImpl::ArktsDynamicComponentRendererImpl(
    const RefPtr<FrameNode>& host, const DynamicParam& dynamicParam)
    : dynamicParam_(dynamicParam)
{
    host_ = WeakPtr(host);
}

RefPtr<DynamicComponentRenderer> DynamicComponentRenderer::Create(
    const RefPtr<FrameNode>& host, const DynamicParam& dynamicParam)
{
    return AceType::MakeRefPtr<ArktsDynamicComponentRendererImpl>(host, dynamicParam);
}

void ArktsDynamicComponentRendererImpl::SetAdaptiveSize(bool adaptiveWidth, bool adaptiveHeight)
{
    adaptiveWidth_ = adaptiveWidth;
    adaptiveHeight_ = adaptiveHeight;
}

void ArktsDynamicComponentRendererImpl::SetBackgroundTransparent(bool backgroundTransparent)
{
    backgroundTransparent_ = backgroundTransparent;
}

bool ArktsDynamicComponentRendererImpl::GetBackgroundTransparent() const
{
    return backgroundTransparent_;
}

void ArktsDynamicComponentRendererImpl::SetUIContentType(UIContentType uIContentType)
{
    uIContentType_ = uIContentType;
    aceLogTag_ = AceLogTag::ACE_DYNAMIC_COMPONENT;
}

bool ArktsDynamicComponentRendererImpl::HasWorkerUsingByWorkerId(int32_t workerId)
{
    if (workerId == INVALID_WORKER_ID) {
        return false;
    }

    std::lock_guard<std::mutex> lock(usingWorkerMutex_);
    return usingWorkers_.find(workerId) != usingWorkers_.end();
}

bool ArktsDynamicComponentRendererImpl::CheckDCMaxConstraintInWorker(int32_t workerId)
{
    if (workerId == INVALID_WORKER_ID) {
        return false;
    }

    std::lock_guard<std::mutex> lock(usingWorkerMutex_);
    auto iter = usingWorkers_.find(workerId);
    if (iter == usingWorkers_.end()) {
        return true;
    }

    return iter->second < DC_MAX_NUM_IN_WORKER;
}

bool ArktsDynamicComponentRendererImpl::CheckWorkerMaxConstraint(int32_t workerId)
{
    if (workerId == INVALID_WORKER_ID) {
        return false;
    }

    std::lock_guard<std::mutex> lock(usingWorkerMutex_);
    auto iter = usingWorkers_.find(workerId);
    if (iter == usingWorkers_.end()) {
        return usingWorkers_.size() < WORKER_MAX_NUM;
    }

    return usingWorkers_.size() < WORKER_MAX_NUM + 1;
}

void ArktsDynamicComponentRendererImpl::AddWorkerUsing(int32_t workerId)
{
    if (workerId == INVALID_WORKER_ID) {
        return;
    }

    std::lock_guard<std::mutex> lock(usingWorkerMutex_);
    auto iter = usingWorkers_.find(workerId);
    if (iter == usingWorkers_.end()) {
        usingWorkers_[workerId] = WORKER_SIZE_ONE;
        return;
    }

    iter->second++;
}

void ArktsDynamicComponentRendererImpl::DeleteWorkerUsing(int32_t workerId)
{
    if (workerId == INVALID_WORKER_ID) {
        return;
    }

    std::lock_guard<std::mutex> lock(usingWorkerMutex_);
    auto iter = usingWorkers_.find(workerId);
    if (iter == usingWorkers_.end()) {
        return;
    }

    if (iter->second <= WORKER_SIZE_ONE) {
        usingWorkers_.erase(iter);
        return;
    }

    iter->second++;
}

void ArktsDynamicComponentRendererImpl::CreateContent()
{
    hostInstanceId_ = Container::CurrentId();
    auto container = Platform::AceContainer::GetContainer(hostInstanceId_);
    CHECK_NULL_VOID(container);
    AddWorkerUsing(dynamicParam_.workerId);
    CreateDynamicContent();
}

void ArktsDynamicComponentRendererImpl::CreateDynamicContent()
{
    TAG_LOGI(aceLogTag_, "CreateDynamicContent");
    ACE_SCOPED_TRACE("[AceDynamicComponent]CreateDynamicContent hostInstanceId[%d]", hostInstanceId_);
    auto container = Platform::AceContainer::GetContainer(hostInstanceId_);
    CHECK_NULL_VOID(container);
    auto hostAbilityContext = container->GetAbilityContext();
    hostJsContext_  = container->GetJsContext();
    std::shared_ptr<TaskWrapper> taskWrapper;
    taskWrapper.reset(ArktsDynamicRendererLoader::GetInstance().CreatEaWorkerTaskWrapper(
        hostInstanceId_, dynamicParam_.workerId));
    if (taskWrapper == nullptr) {
        TAG_LOGE(aceLogTag_, "CreatEaWorkerTaskWrapper failed");
        return;
    }
    taskWrapper->Call([weak = WeakClaim(this), hostAbilityContext]() {
        auto renderer = weak.Upgrade();
        CHECK_NULL_VOID(renderer);
        renderer->InitUiContent(hostAbilityContext.get());
    });
}

RefPtr<SystemWindowScene> ArktsDynamicComponentRendererImpl::GetWindowScene()
{
    RefPtr<SystemWindowScene> hostPattern = nullptr;
    auto host = host_.Upgrade();
    CHECK_NULL_RETURN(host, hostPattern);
    auto hostWindowNode = WindowSceneHelper::FindWindowScene(host);
    CHECK_NULL_RETURN(hostWindowNode, hostPattern);
    auto hostNode = AceType::DynamicCast<FrameNode>(hostWindowNode);
    CHECK_NULL_RETURN(hostNode, hostPattern);
    hostPattern = hostNode->GetPattern<SystemWindowScene>();
    return hostPattern;
}

int32_t ArktsDynamicComponentRendererImpl::GetWindowSceneId()
{
    auto hostPattern = GetWindowScene();
    CHECK_NULL_RETURN(hostPattern, INVALID_WINDOW_ID);
    auto hostSession = hostPattern->GetSession();
    CHECK_NULL_RETURN(hostSession, INVALID_WINDOW_ID);
    return hostSession->GetPersistentId();
}

void ArktsDynamicComponentRendererImpl::BuildDynamicInitialConfig(
    DynamicInitialConfig& dynamicInitialConfig)
{
    dynamicInitialConfig.hostInstanceId = hostInstanceId_;
    dynamicInitialConfig.entryPoint = dynamicParam_.entryPoint;
    dynamicInitialConfig.workerId = dynamicParam_.workerId;
    auto container = Platform::AceContainer::GetContainer(hostInstanceId_);
    CHECK_NULL_VOID(container);
    auto context = container->GetPipelineContext();
    CHECK_NULL_VOID(context);
    if (container->IsSceneBoardWindow()) {
        dynamicInitialConfig.hostWindowInfo.focusWindowId = static_cast<uint32_t>(GetWindowSceneId());
        dynamicInitialConfig.hostWindowInfo.realHostWindowId = context->GetRealHostWindowId();
    } else {
        dynamicInitialConfig.hostWindowInfo.focusWindowId = context->GetFocusWindowId();
        dynamicInitialConfig.hostWindowInfo.realHostWindowId = context->GetRealHostWindowId();
    }
}

void ArktsDynamicComponentRendererImpl::InitUiContent(OHOS::AbilityRuntime::Context *abilityContext)
{
    ACE_SCOPED_TRACE("[AceDynamicComponent]InitUiContent");
    rendererDumpInfo_.ReSet();
    // create UI Content
    TAG_LOGI(aceLogTag_, "create UI Content");
    DcCreateParam param;
    param.isFormRender = true;
    param.aceLogTag = aceLogTag_;
    uiContent_ = ArktsDynamicUIContentImpl::Create(abilityContext,
        ArktsDynamicRendererLoader::GetInstance().GetCurrentThreadAniEnv(),
        VMType::ARK_NATIVE, param);
    CHECK_NULL_VOID(uiContent_);
    uiContent_->SetUIContentType(uIContentType_);
    rendererDumpInfo_.createUiContenTime = GetCurrentTimestamp();

    DynamicInitialConfig dynamicInitialConfig;
    BuildDynamicInitialConfig(dynamicInitialConfig);
    uiContent_->InitializeArktsDynamicUIContentImpl(dynamicInitialConfig);

    auto runtimeContext = Platform::AceContainer::GetRuntimeContext(hostInstanceId_);
    if (runtimeContext) {
        auto uiContentImpl = std::static_pointer_cast<UIContentImpl>(uiContent_);
        if (uiContentImpl) {
            uiContentImpl->UpdateFontScale(runtimeContext->GetConfiguration());
        }
    }

    ContainerScope scope(uiContent_->GetInstanceId());
    RegisterContainerHandler();
    RegisterErrorEventHandler();
    RegisterConfigChangedCallback();
    AttachRenderContext();
    SetUIContentJsContext();
    rendererDumpInfo_.limitedWorkerInitTime = GetCurrentTimestamp();
    TAG_LOGI(aceLogTag_, "foreground dynamic UI content");
    uiContent_->Foreground();
    std::function<void()> contentReadyCallback;
    {
        std::lock_guard<std::mutex> lock(contentReadyMutex_);
        contentReady_ = true;
        if (contentReadyCallback_) {
            contentReadyCallback = std::move(contentReadyCallback_);
        }
    }
    if (contentReadyCallback) {
        contentReadyCallback();
    }
    InitializeDynamicAccessibility();
    rendererDumpInfo_.loadAbcTime = GetCurrentTimestamp();
}

void ArktsDynamicComponentRendererImpl::RegisterContainerHandler()
{
    CHECK_NULL_VOID(uiContent_);
    auto container = Container::GetContainer(uiContent_->GetInstanceId());
    CHECK_NULL_VOID(container);
    auto aceContainer = AceType::DynamicCast<Platform::AceContainer>(container);
    CHECK_NULL_VOID(aceContainer);
    auto host = host_.Upgrade();
    CHECK_NULL_VOID(host);
    auto containerHandler = AceType::DynamicCast<ContainerHandler>(host->GetPattern());
    CHECK_NULL_VOID(containerHandler);
    aceContainer->RegisterContainerHandler(containerHandler);
}

void ArktsDynamicComponentRendererImpl::SetUIContentJsContext()
{
    if (uIContentType_ != UIContentType::DYNAMIC_COMPONENT) {
        return;
    }

    auto jsContext = hostJsContext_.lock();
    CHECK_NULL_VOID(jsContext);
    CHECK_NULL_VOID(uiContent_);
    auto container = Container::GetContainer(uiContent_->GetInstanceId());
    CHECK_NULL_VOID(container);
    auto aceContainer = AceType::DynamicCast<Platform::AceContainer>(container);
    CHECK_NULL_VOID(aceContainer);
    aceContainer->SetJsContext(jsContext);
}

void ArktsDynamicComponentRendererImpl::RegisterErrorEventHandler()
{
    CHECK_NULL_VOID(uiContent_);
    auto errorEventHandler = [weak = WeakClaim(this)](const std::string& code, const std::string& msg) {
        auto renderer = weak.Upgrade();
        if (renderer) {
            renderer->FireOnErrorCallback(WORKER_ERROR, code, msg);
        }
    };
    uiContent_->SetErrorEventHandler(errorEventHandler);
}

void ArktsDynamicComponentRendererImpl::FireOnErrorCallback(
    int32_t code, const std::string& name, const std::string& msg)
{
    auto host = host_.Upgrade();
    CHECK_NULL_VOID(host);
    auto pattern = AceType::DynamicCast<ArktsDynamicPattern>(host->GetPattern());
    CHECK_NULL_VOID(pattern);
    pattern->FireOnErrorCallbackOnUI(code, name, msg);
}

void ArktsDynamicComponentRendererImpl::RegisterSizeChangedCallback()
{
    CHECK_NULL_VOID(uiContent_);
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    taskExecutor->PostSyncTask(
        [weak = WeakClaim(this), aceLogTag = aceLogTag_, instanceId = uiContent_->GetInstanceId()] {
            auto container = Container::GetContainer(instanceId);
            CHECK_NULL_VOID(container);
            auto frontend = AceType::DynamicCast<OHOS::Ace::FormFrontendDeclarative>(container->GetFrontend());
            CHECK_NULL_VOID(frontend);
            auto delegate = frontend->GetDelegate();
            CHECK_NULL_VOID(delegate);
            auto pageRouterManager = delegate->GetPageRouterManager();
            CHECK_NULL_VOID(pageRouterManager);
            auto pageNode = pageRouterManager->GetCurrentPageNode();
            CHECK_NULL_VOID(pageNode);
            auto pagePattern = AceType::DynamicCast<PagePattern>(pageNode->GetPattern());
            CHECK_NULL_VOID(pagePattern);

            auto dynamicPageSizeCallback = [weak, aceLogTag](const SizeF& size) {
                TAG_LOGI(aceLogTag, "card size callback: %{public}s", size.ToString().c_str());
                auto renderer = weak.Upgrade();
                CHECK_NULL_VOID(renderer);
                CHECK_NULL_VOID(renderer->uiContent_);
                auto hostTaskExecutor = renderer->GetHostTaskExecutor();
                CHECK_NULL_VOID(hostTaskExecutor);
                hostTaskExecutor->PostTask(
                    [weak, size]() {
                        auto renderer = weak.Upgrade();
                        CHECK_NULL_VOID(renderer);
                        renderer->HandleCardSizeChangeEvent(size);
                    },
                    TaskExecutor::TaskType::UI, "ArkUIDynamicComponentSizeChanged");
            };
            pagePattern->SetDynamicPageSizeCallback(std::move(dynamicPageSizeCallback));
        }, TaskExecutor::TaskType::UI, "ArkUIRegisterSizeChangedCallback");
}

void ArktsDynamicComponentRendererImpl::HandleCardSizeChangeEvent(const SizeF& size)
{
    if (!adaptiveWidth_ && !adaptiveHeight_) {
        return;
    }
    CHECK_NULL_VOID(uiContent_);
    auto instanceId = uiContent_->GetInstanceId();
    ContainerScope scope(hostInstanceId_);
    auto host = host_.Upgrade();
    CHECK_NULL_VOID(host);
    auto& layout = host->GetLayoutProperty();
    CHECK_NULL_VOID(layout);
    auto padding = layout->CreatePaddingAndBorder();
    auto rect = host->GetTransformRectRelativeToWindow();
    auto width = adaptiveWidth_ ? int32_t(size.Width() + padding.Width()) : rect.Width();
    auto height = adaptiveHeight_ ? int32_t(size.Height() + padding.Height()) : rect.Height();
    if (NearEqual(width, rect.Width()) && NearEqual(height, rect.Height())) {
        TAG_LOGI(aceLogTag_, "[%{public}d] component size not changed: [%{public}f x %{public}f]",
            instanceId, width, height);
        return;
    }
    TAG_LOGI(aceLogTag_,
        "[%{public}d] update component size: [%{public}f x %{public}f] -> [%{public}f x %{public}f]",
        instanceId, rect.Width(), rect.Height(), width, height);
    std::optional<CalcLength> calcWidth =
        adaptiveWidth_ ? std::optional<CalcLength>(CalcLength(width)) : std::nullopt;
    std::optional<CalcLength> calcHeight =
        adaptiveHeight_ ? std::optional<CalcLength>(CalcLength(height)) : std::nullopt;
    layout->UpdateUserDefinedIdealSize(CalcSize(calcWidth, calcHeight));
    host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
}

void ArktsDynamicComponentRendererImpl::RegisterConfigChangedCallback()
{
    CHECK_NULL_VOID(uiContent_);
    auto hostExecutor = GetHostTaskExecutor();
    CHECK_NULL_VOID(hostExecutor);
    hostExecutor->PostTask(
        [hostInstanceId = hostInstanceId_, subInstanceId = uiContent_->GetInstanceId(), aceLogTag = aceLogTag_]() {
            auto configChangedCallback = [subInstanceId, aceLogTag](
                                             const Platform::ParsedConfig& config, const std::string& configuration) {
                TAG_LOGI(aceLogTag, "UpdateConfiguration to subContainer");
                auto subContainer = Platform::AceContainer::GetContainer(subInstanceId);
                CHECK_NULL_VOID(subContainer);
                subContainer->GetTaskExecutor()->PostTask(
                    [weak = WeakClaim(RawPtr(subContainer)), config, configuration]() {
                        auto subContainer = weak.Upgrade();
                        CHECK_NULL_VOID(subContainer);
                        ContainerScope scope(subContainer->GetInstanceId());
                        subContainer->UpdateConfiguration(config, configuration);
                    },
                    TaskExecutor::TaskType::UI, "ArkUIDynamicComponentConfigurationChanged");
            };

            auto hostContainer = Platform::AceContainer::GetContainer(hostInstanceId);
            CHECK_NULL_VOID(hostContainer);
            ACE_SCOPED_TRACE("[AceDynamicComponent]RegisterConfigChangedCallback hostInstanceId[%d],"
                " subInstanceId[%d]", hostInstanceId, subInstanceId);
            hostContainer->AddOnConfigurationChange(subInstanceId, configChangedCallback);
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentConfigurationChanged");
}

void ArktsDynamicComponentRendererImpl::UnRegisterConfigChangedCallback()
{
    CHECK_NULL_VOID(uiContent_);
    auto container = Platform::AceContainer::GetContainer(hostInstanceId_);
    CHECK_NULL_VOID(container);
    container->RemoveOnConfigurationChange(uiContent_->GetInstanceId());
}

void ArktsDynamicComponentRendererImpl::AttachRenderContext()
{
    if (uIContentType_ == UIContentType::DYNAMIC_COMPONENT) {
        AttachRenderContextInDynamicComponent();
    }
}

void ArktsDynamicComponentRendererImpl::AttachRenderContextInDynamicComponent()
{
    CHECK_NULL_VOID(uiContent_);
    auto taskExecutor = GetHostTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    taskExecutor->PostTask([weak = host_, hostInstanceId = hostInstanceId_,
        instanceId = uiContent_->GetInstanceId(), aceLogTag = aceLogTag_,
        backgroundTransparent = GetBackgroundTransparent()]() {
            ContainerScope scope(hostInstanceId);
            auto host = weak.Upgrade();
            CHECK_NULL_VOID(host);
            auto surfaceProxyNode = AceType::DynamicCast<NG::SurfaceProxyNode>(host->GetPattern());
            CHECK_NULL_VOID(surfaceProxyNode);
            auto container = Platform::AceContainer::GetContainer(instanceId);
            CHECK_NULL_VOID(container);
            auto surfaceNode = container->GetFormSurfaceNode(instanceId);
            CHECK_NULL_VOID(surfaceNode);

            auto pipeline = container->GetPipelineContext();
            CHECK_NULL_VOID(pipeline);
            auto pipelineContext = AceType::DynamicCast<NG::PipelineContext>(pipeline);
            CHECK_NULL_VOID(pipelineContext);
            auto rootElement = pipelineContext->GetRootElement();
            CHECK_NULL_VOID(rootElement);
            auto renderContext = rootElement->GetRenderContext();
            CHECK_NULL_VOID(renderContext);
            if (backgroundTransparent) {
                pipeline->SetAppBgColor(Color::TRANSPARENT);
            }
            renderContext->SetClipToFrame(true);
            renderContext->SetClipToBounds(true);
            surfaceProxyNode->AddSurfaceNode(surfaceNode);
            TAG_LOGI(aceLogTag, "add render context of dynamic component for '%{public}d'",
                instanceId);
            ACE_SCOPED_TRACE("[AceDynamicComponent]AttachRenderContextInDynamicComponent "
                "hostInstanceId[%d], subInstanceId[%d]", hostInstanceId, instanceId);
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentAttachRenderContext");
}

void ArktsDynamicComponentRendererImpl::TransferPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
{
    CHECK_NULL_VOID(uiContent_);
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    taskExecutor->PostTask(
        [uiContent = uiContent_, pointerEvent]() {
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            uiContent->ProcessPointerEvent(pointerEvent);
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentProcessPointer");
}

bool ArktsDynamicComponentRendererImpl::TransferKeyEvent(const KeyEvent& keyEvent)
{
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_RETURN(taskExecutor, false);

    auto rawKeyEvent = keyEvent.rawKeyEvent;
    bool result = false;
    std::weak_ptr<UIContent> weak = uiContent_;
    taskExecutor->PostSyncTask(
        [weak, keyEvent, &result, aceLogTag = aceLogTag_]() {
            auto uiContent = weak.lock();
            CHECK_NULL_VOID(uiContent);
            auto subInstanceId = uiContent->GetInstanceId();
            ContainerScope scope(subInstanceId);
            result = uiContent->ProcessKeyEvent(keyEvent.rawKeyEvent);
            TAG_LOGI(aceLogTag, "send key event: %{public}s, result = %{public}d",
                keyEvent.ToString().c_str(), result);
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentProcessKey");
    return result;
}

void ArktsDynamicComponentRendererImpl::TransferFocusState(bool isFocus)
{
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    std::weak_ptr<UIContent> weak = uiContent_;
    taskExecutor->PostTask(
        [weak, isFocus, aceLogTag = aceLogTag_]() {
            auto uiContent = weak.lock();
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            TAG_LOGI(aceLogTag, "send focus state: %{public}d", isFocus);
            if (isFocus) {
                uiContent->Focus();
            } else {
                uiContent->UnFocus();
            }
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentFocusState");
}

void ArktsDynamicComponentRendererImpl::TransferFocusActiveEvent(bool isFocus)
{
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    std::weak_ptr<UIContent> weak = uiContent_;
    taskExecutor->PostTask(
        [weak, isFocus, aceLogTag = aceLogTag_]() {
            auto uiContent = weak.lock();
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            TAG_LOGI(aceLogTag, "send focus active event: %{public}d", isFocus);
            uiContent->SetIsFocusActive(isFocus);
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentFocusActiveEvent");
}

SizeF ArktsDynamicComponentRendererImpl::ComputeAdaptiveSize(const SizeF& size) const
{
    auto width = size.Width();
    auto height = size.Height();
    if (adaptiveWidth_ || adaptiveHeight_) {
        auto host = host_.Upgrade();
        CHECK_NULL_RETURN(host, size);
        auto& layout = host->GetLayoutProperty();
        CHECK_NULL_RETURN(layout, size);
        auto& constraint = layout->GetLayoutConstraint();
        CHECK_NULL_RETURN(constraint, size);
        auto padding = layout->CreatePaddingAndBorder();
        auto maxSize = constraint->maxSize;
        if (adaptiveWidth_) {
            width = maxSize.Width() - padding.Width();
        }
        if (adaptiveHeight_) {
            height = maxSize.Height() - padding.Height();
        }
    }
    return SizeF(width, height);
}

void ArktsDynamicComponentRendererImpl::UpdateViewportConfig(
    const SizeF& size, float density, int32_t orientation, AnimationOption animationOpt, const OffsetF& offset)
{
    if (uIContentType_ == UIContentType::DYNAMIC_COMPONENT) {
        UpdateDynamicViewportConfig(size, density, orientation, animationOpt, offset);
        return;
    }
}

void ArktsDynamicComponentRendererImpl::UpdateParentOffsetToWindow(const OffsetF& offset)
{
    TAG_LOGI(aceLogTag_, "UpdateParentOffsetToWindow");
    auto task = [weak = WeakClaim(this), offset]() {
        auto renderer = weak.Upgrade();
        CHECK_NULL_VOID(renderer);
        auto uiContent = renderer->uiContent_;
        CHECK_NULL_VOID(uiContent);
        ContainerScope scope(uiContent->GetInstanceId());
        auto container = Container::GetContainer(uiContent->GetInstanceId());
        CHECK_NULL_VOID(container);
        auto pipeline = container->GetPipelineContext();
        CHECK_NULL_VOID(pipeline);
        auto pipelineContext = AceType::DynamicCast<NG::PipelineContext>(pipeline);
        CHECK_NULL_VOID(pipelineContext);
        pipelineContext->SetHostParentOffsetToWindow(Offset(offset.GetX(), offset.GetY()));
    };
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    taskExecutor->PostTask(std::move(task), TaskExecutor::TaskType::UI,
        "ArkUIDynamicComponentUpdateParentOffsetToWindow");
}

void ArktsDynamicComponentRendererImpl::DestroyContent()
{
    OnDestroyContent();
    AfterDestroyContent();
}

void ArktsDynamicComponentRendererImpl::OnDestroyContent()
{
    CHECK_NULL_VOID(uiContent_);
    UnRegisterConfigChangedCallback();
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    taskExecutor->PostTask(
        [uiContent = uiContent_, aceLogTag = aceLogTag_]() {
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            TAG_LOGI(aceLogTag, "destroy dynamic UI content");
            uiContent->Destroy();
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentDestroy");
}

void ArktsDynamicComponentRendererImpl::AfterDestroyContent()
{
    if (uIContentType_ == UIContentType::DYNAMIC_COMPONENT) {
        DeleteWorkerUsing(dynamicParam_.workerId);
    }
}

void ArktsDynamicComponentRendererImpl::SearchElementInfoByAccessibilityId(int64_t elementId, int32_t mode,
    int64_t baseParent, std::list<Accessibility::AccessibilityElementInfo>& output)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->SearchElementInfoByAccessibilityId(elementId, mode, baseParent, output);
}

void ArktsDynamicComponentRendererImpl::SearchElementInfosByText(int64_t elementId, const std::string& text,
    int64_t baseParent, std::list<Accessibility::AccessibilityElementInfo>& output)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->SearchElementInfosByText(elementId, text, baseParent, output);
}

void ArktsDynamicComponentRendererImpl::FindFocusedElementInfo(int64_t elementId, int32_t focusType, int64_t baseParent,
    Accessibility::AccessibilityElementInfo& output)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->FindFocusedElementInfo(elementId, focusType, baseParent, output);
}

void ArktsDynamicComponentRendererImpl::FocusMoveSearch(int64_t elementId, int32_t direction, int64_t baseParent,
    Accessibility::AccessibilityElementInfo& output)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->FocusMoveSearch(elementId, direction, baseParent, output);
}

bool ArktsDynamicComponentRendererImpl::NotifyExecuteAction(int64_t elementId, const std::map<std::string,
    std::string>& actionArguments, int32_t action, int64_t offset)
{
    CHECK_NULL_RETURN(uiContent_, false);
    return uiContent_->NotifyExecuteAction(elementId, actionArguments, action, offset);
}

void ArktsDynamicComponentRendererImpl::UpdateDynamicViewportConfig(
    const SizeF& size, float density, int32_t orientation,
    AnimationOption animationOpt, const OffsetF& offset)
{
    CHECK_NULL_VOID(uiContent_);
    auto hostContainer = Platform::AceContainer::GetContainer(hostInstanceId_);
    CHECK_NULL_VOID(hostContainer);
    auto hostContext = hostContainer->GetPipelineContext();
    CHECK_NULL_VOID(hostContext);
    Rosen::SizeChangeReason reason = Rosen::SizeChangeReason::UNDEFINED;
    sptr<Rosen::Session> windowSceneSession = nullptr;
    if (hostContainer->IsSceneBoardWindow()) {
        auto windowScenePattern = GetWindowScene();
        if (windowScenePattern) {
            windowSceneSession = windowScenePattern->GetSession();
            if (windowSceneSession) {
                reason = static_cast<Rosen::SizeChangeReason>(windowSceneSession->GetSizeChangeReason());
                orientation = GetSCBOrientation(windowScenePattern->GetHost());
            }
        }
    }

    auto adaptiveSize = ComputeAdaptiveSize(size);
    ViewportConfig vpConfig(adaptiveSize.Width(), adaptiveSize.Height(), density);
    vpConfig.SetPosition(0, 0);
    vpConfig.SetOrientation(orientation);
    auto option = CopyAnimationOption(animationOpt);
    auto hostRSTransaction =
        ArktsDynamicComponentRendererImpl::GetSyncRSTransactionByInstanceId(hostInstanceId_);
    uint64_t syncId = 0;
    if (hostRSTransaction && reason == Rosen::SizeChangeReason::ROTATION) {
        syncId = hostRSTransaction->GetSyncId();
        auto subRSUIContext =
            ArktsDynamicComponentRendererImpl::GetRSUIContextByInstanceId(uiContent_->GetInstanceId());
        auto subRSTransaction =
            ArktsDynamicComponentRendererImpl::GetCommonRSTransactionByRSUIcontext(subRSUIContext);
        if (subRSUIContext && subRSTransaction) {
            hostRSTransaction->AddSubSyncTransaction(
                subRSTransaction, subRSUIContext->GetToken(), syncId);
        } else {
            TAG_LOGW(aceLogTag_, "AddSubSyncTransaction failed due to invalid subRSUIContext[%{public}d],"
            " subRSTransaction[%{public}d]", subRSUIContext != nullptr, subRSTransaction != nullptr);
        }
    }

    bool optionIsValid = option && option->IsValid();
    TAG_LOGI(aceLogTag_, "Update DC[%{public}d] Size: %{public}s -> [%{public}d x %{public}d], "
        "reason:[%{public}d], hasSyncTransaction:[%{public}d], orientation:[%{public}d], "
        "syncId:[%{public}s], optionIsValid:[%{public}d]", uiContent_->GetInstanceId(),
        size.ToString().c_str(), vpConfig.Width(), vpConfig.Height(), static_cast<int32_t>(reason),
        hostRSTransaction != nullptr, orientation, std::to_string(syncId).c_str(), optionIsValid);
    ACE_SCOPED_TRACE("[AceDynamicComponent]Update DC[%d] Size:[%s]->[%d x %d], reason:[%d], "
        "hasSyncTransaction:[%d], orientation:[%d], syncId:[%s], optionIsValid:[%d]",
        uiContent_->GetInstanceId(), size.ToString().c_str(), vpConfig.Width(), vpConfig.Height(),
        static_cast<int32_t>(reason), hostRSTransaction != nullptr, orientation,
        std::to_string(syncId).c_str(), optionIsValid);
    auto task = [weak = WeakClaim(this), vpConfig, option, aceLogTag = aceLogTag_,
        offset, reason, hostRSTransaction, syncId]() {
        auto renderer = weak.Upgrade();
        CHECK_NULL_VOID(renderer);
        auto uiContent = std::static_pointer_cast<UIContentImpl>(renderer->uiContent_);
        CHECK_NULL_VOID(uiContent);
        ContainerScope scope(uiContent->GetInstanceId());
        ViewportConfig config(vpConfig.Width(), vpConfig.Height(), vpConfig.Density());
        config.SetPosition(vpConfig.Left(), vpConfig.Top());
        config.SetOrientation(vpConfig.Orientation());
        if (renderer->uIContentType_ == UIContentType::DYNAMIC_COMPONENT) {
            renderer->UpdateParentOffsetToWindow(offset);
            config.SetPosition(offset.GetX(), offset.GetY());
        }
        auto removeTransaction = [hostRSTransaction, reason, uiContent, aceLogTag, syncId]() {
            if (hostRSTransaction && reason == Rosen::SizeChangeReason::ROTATION) {
                auto subRSUIContext = ArktsDynamicComponentRendererImpl::GetRSUIContextByInstanceId(
                    uiContent->GetInstanceId());
                CHECK_NULL_VOID(subRSUIContext);
                TAG_LOGI(aceLogTag, "RemoveSubSyncTransaction syncId: %{public}s",
                    std::to_string(syncId).c_str());
                hostRSTransaction->RemoveSubSyncTransaction(subRSUIContext->GetToken(), syncId);
            }
        };
        if (renderer->viewport_.Width() == config.Width()
            && renderer->viewport_.Height() == config.Height()
            && renderer->density_ == config.Density()) {
            TAG_LOGW(aceLogTag, "card viewport not changed");
            removeTransaction();
            return;
        }
        renderer->viewport_.SetWidth(config.Width());
        renderer->viewport_.SetHeight(config.Height());
        renderer->density_ = config.Density();
        bool optionIsValid = option == nullptr ? false : option->IsValid();
        TAG_LOGI(aceLogTag, "Handle Update DC[%{public}d] config:[%{public}s], syncId:[%{public}s],"
            " optionIsValid:[%{public}d], reason:[%{public}d], hasSyncTransaction:[%{public}d]",
            uiContent->GetInstanceId(), config.ToString().c_str(),  std::to_string(syncId).c_str(),
            optionIsValid, static_cast<int32_t>(reason), hostRSTransaction != nullptr);
        ACE_SCOPED_TRACE("Handle Update DC[%d] config:[%s], syncId:[%s], optionIsValid:[%d], reason:[%d],"
            " hasSyncTransaction:[%d]", uiContent->GetInstanceId(), config.ToString().c_str(),
            std::to_string(syncId).c_str(), optionIsValid, static_cast<int32_t>(reason),
            hostRSTransaction == nullptr);
        if (option == nullptr) {
            TAG_LOGI(aceLogTag, "option points to nullptr");
            removeTransaction();
            return;
        }
        uiContent->UpdateViewportConfigWithAnimation(
            config, static_cast<Rosen::WindowSizeChangeReason>(reason), *option, hostRSTransaction);
        removeTransaction();
    };
    bool contentReady = false;
    {
        std::lock_guard<std::mutex> lock(contentReadyMutex_);
        contentReady = contentReady_;
        if (!contentReady) {
            contentReadyCallback_ = std::move(task);
        }
    }
    if (contentReady) {
        auto taskExecutor = GetTaskExecutor();
        CHECK_NULL_VOID(taskExecutor);
        taskExecutor->PostTask(std::move(task), TaskExecutor::TaskType::UI,
            "ArkUIDynamicComponentUpdateViewport", PriorityType::VIP);
    }
}

int32_t ArktsDynamicComponentRendererImpl::GetSCBOrientation(const RefPtr<FrameNode>& windowSceneNode)
{
    CHECK_NULL_RETURN(windowSceneNode, 0);
    auto parent = windowSceneNode->GetParent();
    while (parent && parent->GetTag() != V2::SCREEN_ETS_TAG) {
        parent = parent->GetParent();
    }
    CHECK_NULL_RETURN(parent, 0);
    auto parentNode = AceType::DynamicCast<FrameNode>(parent);
    CHECK_NULL_RETURN(parentNode, 0);
    auto screenPattern = parentNode->GetPattern<NG::ScreenPattern>();
    CHECK_NULL_RETURN(screenPattern, 0);
    auto screenSession = screenPattern->GetScreenSession();
    CHECK_NULL_RETURN(screenSession, 0);
    return static_cast<int32_t>(screenSession->GetScreenProperty().GetDisplayOrientation());
}

std::shared_ptr<Rosen::RSUIContext> ArktsDynamicComponentRendererImpl::GetRSUIContextByInstanceId(
    int32_t instanceId)
{
    auto pipelineContext = NG::PipelineContext::GetContextByContainerId(instanceId);
    CHECK_NULL_RETURN(pipelineContext, nullptr);
    auto window = pipelineContext->GetWindow();
    CHECK_NULL_RETURN(window, nullptr);
    auto rsUIDirector =  window->GetRSUIDirector();
    CHECK_NULL_RETURN(rsUIDirector, nullptr);
    return rsUIDirector->GetRSUIContext();
}

std::shared_ptr<Rosen::RSTransaction> ArktsDynamicComponentRendererImpl::GetCommonRSTransactionByRSUIcontext(
    const std::shared_ptr<Rosen::RSUIContext>& rsUIContext)
{
    CHECK_NULL_RETURN(rsUIContext, nullptr);
    auto transactionController = rsUIContext->GetSyncTransactionHandler();
    CHECK_NULL_RETURN(transactionController, nullptr);
    return transactionController->GetCommonRSTransaction();
}

std::shared_ptr<Rosen::RSTransaction> ArktsDynamicComponentRendererImpl::GetSyncRSTransactionByInstanceId(
    int32_t instanceId)
{
    auto rsUIContext = ArktsDynamicComponentRendererImpl::GetRSUIContextByInstanceId(instanceId);
    CHECK_NULL_RETURN(rsUIContext, nullptr);
    auto transactionController = rsUIContext->GetSyncTransactionHandler();
    CHECK_NULL_RETURN(transactionController, nullptr);
    return transactionController->GetRSTransaction();
}

void ArktsDynamicComponentRendererImpl::TransferAccessibilityHoverEvent(
    float pointX, float pointY, int32_t sourceType, int32_t eventType, int64_t timeMs)
{
    CHECK_NULL_VOID(uiContent_);
    auto host = host_.Upgrade();
    CHECK_NULL_VOID(host);
    auto pattern = host->GetPattern();
    CHECK_NULL_VOID(pattern);
    auto container = Container::GetContainer(uiContent_->GetInstanceId());
    CHECK_NULL_VOID(container);
    auto front = container->GetFrontend();
    CHECK_NULL_VOID(front);
    auto jsAccessibilityManager = front->GetAccessibilityManager();
    CHECK_NULL_VOID(jsAccessibilityManager);
    auto uiExtensionId = pattern->GetUiExtensionId();
    TAG_LOGI(aceLogTag_, "uiExtensionId: %{public}d", uiExtensionId);
    jsAccessibilityManager->SetUiextensionId(uiExtensionId);
    uiContent_->HandleAccessibilityHoverEvent(pointX, pointY, sourceType, eventType, timeMs);
}

RefPtr<TaskExecutor> ArktsDynamicComponentRendererImpl::GetTaskExecutor()
{
    CHECK_NULL_RETURN(uiContent_, nullptr);
    auto container = Container::GetContainer(uiContent_->GetInstanceId());
    CHECK_NULL_RETURN(container, nullptr);
    return container->GetTaskExecutor();
}

RefPtr<TaskExecutor> ArktsDynamicComponentRendererImpl::GetHostTaskExecutor()
{
    auto container = Container::GetContainer(hostInstanceId_);
    CHECK_NULL_RETURN(container, nullptr);
    return container->GetTaskExecutor();
}

void ArktsDynamicComponentRendererImpl::Dump(RendererDumpInfo &rendererDumpInfo)
{
    rendererDumpInfo = rendererDumpInfo_;
}

void ArktsDynamicComponentRendererImpl::NotifyUieDump(const std::vector<std::string>& params,
    std::vector<std::string>& info)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->DumpInfo(params, info);
}

void ArktsDynamicComponentRendererImpl::TransferAccessibilityChildTreeRegister(
    uint32_t windowId, int32_t treeId, int64_t accessibilityId)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->RegisterAccessibilityChildTree(windowId, treeId, accessibilityId);
}

void ArktsDynamicComponentRendererImpl::TransferAccessibilityChildTreeDeregister()
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->DeregisterAccessibilityChildTree();
}

void ArktsDynamicComponentRendererImpl::TransferAccessibilityDumpChildInfo(
    const std::vector<std::string>& params, std::vector<std::string>& info)
{
    CHECK_NULL_VOID(uiContent_);
    uiContent_->AccessibilityDumpChildInfo(params, info);
}

void ArktsDynamicComponentRendererImpl::InitializeDynamicAccessibility()
{
    if (uIContentType_ != UIContentType::DYNAMIC_COMPONENT) {
        return;
    }
    auto dynamicHost = host_.Upgrade();
    CHECK_NULL_VOID(dynamicHost);
    auto pattern = AceType::DynamicCast<DynamicPattern>(dynamicHost->GetPattern());
    CHECK_NULL_VOID(pattern);
    pattern->InitializeAccessibility();
}

void ArktsDynamicComponentRendererImpl::NotifyForeground()
{
    if (isForeground_) {
        return;
    }

    CHECK_NULL_VOID(uiContent_);
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    isForeground_ = true;
    taskExecutor->PostTask(
        [uiContent = uiContent_, aceLogTag = aceLogTag_]() {
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            TAG_LOGI(aceLogTag, "NotifyForeground");
            uiContent->Foreground();
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentNotifyForeground");
}

void ArktsDynamicComponentRendererImpl::NotifyBackground()
{
    if (!isForeground_) {
        return;
    }

    CHECK_NULL_VOID(uiContent_);
    auto taskExecutor = GetTaskExecutor();
    CHECK_NULL_VOID(taskExecutor);
    isForeground_ = false;
    taskExecutor->PostTask(
        [uiContent = uiContent_, aceLogTag = aceLogTag_]() {
            CHECK_NULL_VOID(uiContent);
            ContainerScope scope(uiContent->GetInstanceId());
            TAG_LOGI(aceLogTag, "NotifyBackground");
            uiContent->Background();
        },
        TaskExecutor::TaskType::UI, "ArkUIDynamicComponentNotifyBackground");
}
} // namespace OHOS::Ace::NG
